package net.j4love.dubbo.extension.filter;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.support.RpcUtils;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
 *
 * 为每次 rpc 调用记录日志
 * @author He Peng
 * @create 2017-07-18 22:51
 * @update 2017-07-18 22:51
 * @updatedesc : 更新说明
 * @see
 */

@Activate(group = {Constants.CONSUMER,Constants.PROVIDER})
public class RpcInvokeLogFilter implements Filter {

    private static final Logger LOG = LoggerFactory.getLogger(RpcInvokeLogFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {

        RpcContext rpcContext = RpcContext.getContext();

        StringBuilder invokeBeforeLogBuilder = new StringBuilder();
        if (rpcContext.isConsumerSide()) {
            invokeBeforeLogBuilder.append(" [").append(rpcContext.getLocalHost())
                    .append(":").append(rpcContext.getLocalPort())
                    .append("]").append(" -> ").append("[")
                    .append(rpcContext.getRemoteHost()).append(":")
                    .append(rpcContext.getRemotePort()).append("]");
        } else if (rpcContext.isProviderSide()) {
            invokeBeforeLogBuilder.append(" [").append(rpcContext.getRemoteHost())
                    .append(":").append(rpcContext.getRemotePort())
                    .append("]").append(" -> ").append("[")
                    .append(rpcContext.getLocalHost()).append(":")
                    .append(rpcContext.getLocalPort()).append("]");
        }

        invokeBeforeLogBuilder.append(" Invoke Interface [")
                            .append(invoker.getInterface())
                            .append("]").append(" Method [")
                            .append(RpcUtils.getMethodName(invocation))
                            .append("] ParameterTypes [")
                            .append(Arrays.deepToString(RpcUtils.getParameterTypes(invocation)))
                            .append("]").append(" Arguments [")
                            .append(Arrays.deepToString(RpcUtils.getArguments(invocation)));

        if (LOG.isInfoEnabled()) {
            LOG.info(invokeBeforeLogBuilder.toString());
        }

        long invokeBeforeTimestamp = System.currentTimeMillis();

        Result invokedResult = invoker.invoke(invocation);

        long invokedCompleteTimestamp = System.currentTimeMillis();
        long timeCost = invokedCompleteTimestamp - invokeBeforeTimestamp;
        StringBuilder invokeCompleteLogBuilder = new StringBuilder();
        invokeCompleteLogBuilder.append("] Return Value [").append(invokedResult.getValue())
                                .append("] Time Cost [").append(timeCost).append("] ms");

        if (LOG.isInfoEnabled()) {
            LOG.info(invokeCompleteLogBuilder.toString());
        }
        return invokedResult;
    }
}
